define(['jquery'], function($) {
	(function($) {
		/** 
		 *  路由规则注册 eg:index.html#2/1
		 * 	定义hash事件 锚点定义规则#{id1}/{id2}
		 *  返回对象:返回键值对对象{id1:v1,id2:v2,...}
		 *  eg:
		 *  $route:{
		 *	{id1}/{id2}:function(obj){
		 *	 	alert(obj.id1+'||'+obj.id2);
		 *	  }
		 *  }
		 *  
		 *  $.route(function 或 object<key, function 或 object> 或 array<object<key, function>>);
		 *  
		 *  1 必须传入一个 function ($tplHtml,$tplData,$objfn,$retobj) 方法用于集中处理信息
		 *  2 注册路由规则 {"home":function($retobj){}} 或 {"home":{
		 *  																				redirectTo:"string 或 function(retobj) return string; 重新定向内容 ng: home",
		 *  																				resolve:"string 或 array<string> ,依赖的控制器或组 (不会执行model)  ng: homeController",
		 *  																				templateUrl:"string ,模板地址 加载html内容   ng: demo.html ",
		 *  																				template:"string 或 function(retobj) return string; ,模板地址内容 是html内容 如果和templateUrl 同时设置只会执行 templateUrl ng:<html>内容</html>",
		 *  																				controller:"string  控制器 在所有控制器执行完成后执行控制器 ng: homeController"
		 *  																				}
		 *  																	}
		 *  
		 **/
		$.extend({
			route : function($route) {
				CHECKGLOBAL_ROUTE();
				CHECKGLOBAL_LOADHTML();
				
				//检测变量
				
				// 将路由添加到特定的全局变量
				for(url in $route){
					window.GLOBAL.$ROUTE[url]=$route[url];
				}
				// 遇到历史会跳
				window.GLOBAL.$HISTORY_ROBACK=false;
				window.onhashchange = function() {
					var hashstr = location.hash;
					var _href=location.href;
					var _dhref=decodeURIComponent(_href);
					if(_dhref.indexOf('\'')!=-1||_dhref.indexOf('\"')!=-1||_dhref.indexOf('>')!=-1||_dhref.indexOf('<')!=-1){
						alert("URL地址存在非法字符 ( '  \"  >  < ) :  \r\n"+_href);
						return;
					}
					
					// 如果hash为空 那么不做处理
					if(hashstr=='' && typeof window.GLOBAL.$HISTORY !='undefined'){
						location.hash = window.GLOBAL.$HISTORY;
						window.GLOBAL.$HISTORY_ROBACK=true;
						return;
					}
					// 如果是从历史里面设置地址那么不加载内容直接return
					if(window.GLOBAL.$HISTORY_ROBACK){
						window.GLOBAL.$HISTORY_ROBACK=false;
						return;
					}
					window.GLOBAL.$HISTORY=hashstr;
					//路由前拦截器
					if(typeof window.GLOBAL.$ROUTEBEFORE === 'function'){
						window.GLOBAL.$ROUTEBEFORE(hashstr);
					}
					hashstr = hashstr.substring(1);
					var globalUrl;
					for(url in window.GLOBAL.$ROUTE){
						
						// 转换/{id1}/{id2} 为/([^\/]*)/([^\/]*) 正则表达式
						var urlpattern = url.replace(/\{.*?\}/ig,'([^\/]*)');
						// 加上尾边界$
						urlpattern = urlpattern+"$";
						var regExp = new RegExp(urlpattern);
						//hash匹配，能匹配上，1:提取key 2:提取值 3:执行回调函数
						if(regExp.test(hashstr)){
							if(typeof window.GLOBAL._historyrecord =='undefined'){
								window.GLOBAL._historyrecord=[];
							}
							window.GLOBAL._historyrecord.unshift(hashstr);
							//1 提取key
							var key = url.replace(/{/g,'');
							key = key.replace(/}/g,'');
							var keyarry = key.match(regExp);
							//2 提取值
							var valuearray = hashstr.match(regExp);
							var len = valuearray.length;
							var retobj = {};
							// 设置通配符参数值
							for(i=1;i<len;i++){
								retobj[keyarry[i]] = valuearray[i];
							}
							window.GLOBAL.$PARAM=retobj;
							
							// 全局获取到的变量设置到局部变量
							var _objfn=window.GLOBAL.$ROUTE[url];
							
							// 判断传进来的是对象还是函数
							if(typeof _objfn === 'object'){
								
								// 打开新页面
								if(typeof _objfn.openTo === 'string'){
									 window.open(_objfn.openTo);
								}else if(typeof _objfn.redirectTo === 'string'){
									// 1.判断重定向
									location.hash = '#' + _objfn.redirectTo;
								}else if(typeof _objfn.redirectTo === 'function'){
									// 重定向的地址。
									location.hash = '#' + _objfn.redirectTo(retobj);
								}else{
									// 定义模板传输对象
									var _tplData = {};
									_tplData.sysconfig={};
									if(typeof window.GLOBAL === 'object' && typeof window.GLOBAL.$SYSCONFIG === 'object'){
										_tplData.sysconfig=window.GLOBAL.$SYSCONFIG;
									}
									// 2.判断 取模板方法
									var _tplHtml;
									if(typeof _objfn.templateUrl === 'string'){
										_tplHtml=$.setHTML(_objfn.templateUrl);
									}else if(typeof _objfn.template === 'string'){
										_tplHtml=_objfn.template;
									}else if(typeof _objfn.template === 'function'){
										_tplHtml=_objfn.template(retobj);
									}
								
									//  3.判断依赖 控制器
									if(typeof _objfn.resolve === 'object'){
										// 执行依赖 控制器 组
										for(_index in _objfn.resolve){
											window.GLOBAL.$CONTROLLERS[_objfn.resolve[_index]](function($modeldata){
												if(typeof $modeldata === 'object'){
													_tplData=$modeldata;
												}
											},_tplHtml,_tplData,_objfn,retobj);
										}
									}else if(typeof _objfn.resolve === 'string'){
										// 执行依赖 控制器
										window.GLOBAL.$CONTROLLERS[_objfn.resolve](function($modeldata){
											if(typeof $modeldata === 'object'){
												_tplData=$modeldata;
											}
										},_tplHtml,_tplData,_objfn,retobj);
									}
									
									
									// 4. 判断控制器
									if(typeof _objfn.controller === 'string'){

										if(_objfn.controller=="default" || _objfn.controller=="mainController"){
												// 执行控制器
												
												window.GLOBAL.$CONTROLLERS[_objfn.controller](function($modeldata){
													// 后面交给全局处理方法
													if(typeof $modeldata != 'object'){
														$modeldata=_tplData;
													}
													// 5.判断是否使用全局处理方法
													if(typeof _tplHtml === 'string' && ( typeof _objfn.isglobalFn === 'undefined' || typeof _objfn.isglobalFn === 'true') && typeof window.GLOBAL.$ROTEFN === 'function'){
														// 执行全局处理方法
														window.GLOBAL.$ROTEFN(_tplHtml,$modeldata,_objfn,retobj);
													}
												},_tplHtml,_tplData,_objfn,retobj);

										}else{

											require([_objfn.controller],function(){
												if(typeof window.GLOBAL.$CONTROLLERS[_objfn.controller] === 'function'){
												// 执行控制器
												window.GLOBAL.$CONTROLLERS[_objfn.controller](function($modeldata){
													// 后面交给全局处理方法
													if(typeof $modeldata != 'object'){
														$modeldata=_tplData;
													}
													// 5.判断是否使用全局处理方法
													if(typeof _tplHtml === 'string' && ( typeof _objfn.isglobalFn === 'undefined' || typeof _objfn.isglobalFn === 'true') && typeof window.GLOBAL.$ROTEFN === 'function'){
														// 执行全局处理方法
														window.GLOBAL.$ROTEFN(_tplHtml,$modeldata,_objfn,retobj);
													}
												},_tplHtml,_tplData,_objfn,retobj);
												}
											})

										}
									}else{
										// 执行全局处理方法
										
										// 5.判断是否使用全局处理方法
										if(typeof _tplHtml === 'string' && ( typeof _objfn.isglobalFn === 'undefined' || typeof _objfn.isglobalFn === 'true') && typeof window.GLOBAL.$ROTEFN === 'function'){
											// 执行全局处理方法
											window.GLOBAL.$ROTEFN(_tplHtml,_tplData,_objfn,retobj);
										}
									}
									
								}
							}else if(typeof _objfn === 'function'){
								// 回调函数
								_objfn(retobj);
							}
							break;
						}else{
							continue;
						}
					}
				};
				// 注册成为全局变量
				if(window.GLOBAL && typeof window.GLOBAL.special ==='undefined'){
					window.GLOBAL.special=function(){
						var appv = window.navigator.appVersion;
						if (appv.indexOf('MSIE 7') === -1 && appv.indexOf('MSIE 6') === -1){
							window.onhashchange();
							return;
						}
						// 版本兼容问题 
						var lurl = window.location.href;
						window.setInterval(function() {
							var curl = window.location.href;
							if (lurl == curl)
								return;
							lurl = curl;
							if (window.onhashchange)
								window.onhashchange();
						}, 500);
					}
					window.GLOBAL.special();
				}
				return this;
			}
		});
		
		$.extend({
			routeBefore : function($routeBeforeFn) {
				if(typeof $routeBeforeFn === 'function'){
					window.GLOBAL.$ROUTEBEFORE = $routeBeforeFn;
				}
				return this;
			}
		});
		$.fn.extend({ routeBefore:$.routeBefore});
		
		$.extend({
			routeFn : function($routeFn) {
				if(typeof $routeFn === 'function'){
					window.GLOBAL.$ROTEFN = $routeFn;
				}
				return this;
			}
		});
		$.fn.extend({ routeFn:$.routeFn});
		
		
		/** 

		 * 控制器定义方式
		 * 
		 * **** 控制器定义  参数说明
		 * 
		 * @param controllerName 填写控制器名字
		 * 
		 * @param $model 控制器model 方法 $model({});  必须调用 用于传输数据给模板
		 * @param $tplHtml 模板内容
		 * @param $defobj  控制器传入的默认对象  可以传回给  控制器$model($defobj);
		 * @param $modelobj 模块 对象 模块 定义时候指定的对象
		 * @param $paramobj 标签param 参数对象 
		 * @param $this  标签jQuery 对象 (路由请求时候没有该对象)
		 * 
		 * ng:
		 * 
		 * $.controller("controllerName" ,  function( $model , $tplHtml , $defobj , $modelobj , $paramobj , $this){
		 * 		// 此方法必须调用不然数据没法输出到页面用于执行  
		 * 		$model($defobj);
		 * });
		 * 
		 **/
		$.extend({
			controller : function($controllerName,$controllerFn) {
				CHECKGLOBAL_CONTROLLERS();
				// 将对象加入到全局变量
				if(typeof $controllerFn === 'function'){
					window.GLOBAL.$CONTROLLERS[$controllerName]=$controllerFn;
				}else{
					window.GLOBAL.$CONTROLLERS[$controllerName]=function(){};
				}
				return this;
			}
		});
		
		$.fn.extend({ controller:$.controller});
		
		/** 
		 *  获取html内容
		 **/
		$.extend({
			setHTML : function($url,$data) {
				if(typeof $data != 'object'){$data = {};}
				var _html='';
				// 判断内存中是有已经下载的html 
				CHECKGLOBAL_LOADHTML();
				if(typeof window.GLOBAL.$LOADHTML  === 'object' && typeof window.GLOBAL.$LOADHTML[$url] === 'string'){
					_html = window.GLOBAL.$LOADHTML[$url];
				}else{
					// 异步请求html
					$data._r=Math.random();
			 		$.ajax({
						url: $url,
				        data:$data,
				        success: function(html) {
				        	_html = html;
				        },
				        async:false
					});
			 		window.GLOBAL.$LOADHTML[$url] = _html;
				}
		 		
				return _html;
			}
		});
		$.fn.extend({ setHTML:$.setHTML});
		
		/**
		 * 获取方法的参数名字
		 */
		function getArgs(func) {
			 // 先用正则匹配,取得符合参数模式的字符串.
			 // 第一个分组是这个: ([^)]*) 非右括号的任意字符
			 var args = func.toString().match(/function(.*?)\((.*?)\)/)[2];
			 // 用逗号来分隔参数(arguments string).
			 return args.split(",").map(function(arg) {
			  // 去除注释(inline comments)以及空格
			  return arg.replace(/\/\*.*\*\//, "").trim();
			 }).filter(function(arg) {
			  // 确保没有 undefined.
			  return arg;
			 });
		};

		$.extend({
			fobind : function($fn,$obj,$objef,$satisfyfn){
				if(typeof $fn === 'function'){
					if(typeof $obj != 'object'){
						$obj={};
					}
					if(typeof $objef != 'object'){
						$objef={};
					}
					var _fnargs=getArgs($fn);
					for(var i in _fnargs){
						if(typeof $objef[_fnargs[i]] === 'function'){$objef[_fnargs[i]]();}
						_fnargs[i]=$obj[_fnargs[i]];
						
					}
					if(typeof $satisfyfn === 'function'){
						$satisfyfn(function(){
							if(_fnargs.length > 0){
								$fn(_fnargs[0],_fnargs[1],_fnargs[2],_fnargs[3],_fnargs[4],_fnargs[5],_fnargs[6],_fnargs[7],_fnargs[8],_fnargs[9],_fnargs[10],_fnargs[11],_fnargs[12],_fnargs[13],_fnargs[14]);
							}else{
								$fn();
							}
						});
					}else{
						if(_fnargs.length > 0){
							$fn(_fnargs[0],_fnargs[1],_fnargs[2],_fnargs[3],_fnargs[4],_fnargs[5],_fnargs[6],_fnargs[7],_fnargs[8],_fnargs[9],_fnargs[10],_fnargs[11],_fnargs[12],_fnargs[13],_fnargs[14]);
						}else{
							$fn();
						}
					}
				}
			}
		});
		$.fn.extend({ fobind:$.fobind});
		
		var CHECKGLOBAL = function(){
			// 检测全局变量
			if(typeof window.GLOBAL != 'object'){
				window.GLOBAL={};
			}
			
		};
		// 检测全局变量
		var CHECKGLOBAL_LOADHTML = function(){
			CHECKGLOBAL();
			if(typeof window.GLOBAL.$LOADHTML != 'object'){
				window.GLOBAL.$LOADHTML={};
			}
		};
		// 检测全局变量
		var CHECKGLOBAL_ROUTE = function(){
			CHECKGLOBAL();
			if(typeof window.GLOBAL.$ROUTE != 'object'){
				window.GLOBAL.$ROUTE={};
			}
		};
		// 检测全局变量
		var CHECKGLOBAL_CONTROLLERS = function(){
			CHECKGLOBAL();
			if(typeof window.GLOBAL.$CONTROLLERS != 'object'){
				window.GLOBAL.$CONTROLLERS={};
			}
		};
	})(jQuery);
});